﻿using Abp.Collections.Extensions;
using Abp.Dependency;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.Extensions;
using Abp.Json;
using Abp.Logging;
using Abp.Runtime.Session;
using Abp.Timing;
using Abp.UI;
using Castle.Core.Internal;
using JetBrains.Annotations;
using Mt.Site.Core.Base.Tree;
using Mt.Site.Core.Organizations.UserCache;
using Mt.Site.Core.Organizations.UserCache.Models;
using Mt.Site.Core.WorkFlows.Design;
using Mt.Site.Core.WorkFlows.Diy;
using Mt.Site.Core.WorkFlows.Diy.Plugin;
using Mt.Site.Core.WorkFlows.Enum;
using Mt.Site.Core.WorkFlows.Process.Entities;
using Mt.Site.Core.WorkFlows.Process.Models;
using Mt.Site.Core.WorkFlows.Process.Stores;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Mt.Site.Core.WorkFlows.Process.Impl
{
    /*
 规则： 分支 每次发起分支选择一批人员，办理完毕后送回分支发起人，
            1. 中间不能临时新增人员
            2. 不能添加重复人员（有待办任务的不能添加）
        主线 稿件进入下一步骤时，添加一批人员， 此后办理中可以通过自定义操作补充办理人员（添加到主线： 
                有两种方式，1是添加人自己的任务不结束，以平行的方式添加会办人员，2是自己的任务结束，添加后续审核人员， 它们在撤回时代码逻辑不一样）
             主线任务可以添加传阅人员， 传阅的模式时多人并行，传阅支持跨步骤完成
 */
    public class WorkFlowManager : IWorkFlowManager, ITransientDependency, IDisposable
    {
        public Guid PaperId { get; private set; }

        public IAbpSession AbpSession { get; set; }

        public IRepository<WorkFlowPaper, Guid> WorkFlowPaperRepository { get; private set; }

        public IWorkFlowProcessStore WorkFlowProcessStore { get; private set; }

        public IWokFlowLogStore WokFlowLogStore { get; private set; }

        public IUserAndUnitFinder UserAndUnitFinder { get; set; }
        private readonly IUnitOfWorkManager _unitOfWorkManager;

        public IIocResolver IocResolver { get; private set; }
        public IPaperContext CurrentPaper { get; private set; }

        public IWorkFlowFactory WorkFlowFactory { get; private set; }

        public WorkFlowPluginFunctionsBase WorkFlowPluginFunction { get; private set; }

        public WorkFlowNodePluginFunctionsBase WorkFlowNodePluginFunction { get; private set; }

        private readonly IWorkFlowPluginManager _workFlowPluginManager;

        private List<WorkFlowLogDto> _logData;
        private List<Guid> _traces;                             //已走过的节点的序号集合

        private List<WorkFlowProcessDto> _processData;
        private List<WorkFlowProcessDto> _processDataWithArchive;
        private List<WorkFlowRelationshipDto> _workFlowRelationshipData;
        private List<WorkFlowRelationshipDto> _workFlowRelationshipDataWithCanceled;
        private ActionState? _actionState = null;
        private NodeListCache _nextNodeListCache = null;
        private List<WorkFlowProcessDto> _currentProcessDataList = null;
        private WorkFlowProcessDto _currentProcessData = null;

        private readonly IRepository<WorkFlowRunTime, long> _workFlowRuntimeRepository;

        public WorkFlowManager(
            IRepository<WorkFlowPaper, Guid> workFlowPaperRepository,
            IWokFlowLogStore wokFlowLogStore,
            IWorkFlowProcessStore workFlowProcessStore,
            IWorkFlowFactory workFlowFactory,
            IIocResolver iocResolver,
            IUserAndUnitFinder userAndUnitFinder,
            IUnitOfWorkManager unitOfWorkManager,
            IWorkFlowPluginManager workFlowPluginManager,
            IRepository<WorkFlowRunTime, long> workFlowRuntimeRepository)
        {
            WorkFlowPaperRepository = workFlowPaperRepository;
            _workFlowRuntimeRepository = workFlowRuntimeRepository;
            WokFlowLogStore = wokFlowLogStore;
            WorkFlowProcessStore = workFlowProcessStore;
            WorkFlowFactory = workFlowFactory;
            IocResolver = iocResolver;
            UserAndUnitFinder = userAndUnitFinder;
            _unitOfWorkManager = unitOfWorkManager;
            _workFlowPluginManager = workFlowPluginManager;

            AbpSession = NullAbpSession.Instance;
        }


        public async Task Initialize(Guid paparId)
        {
            this.PaperId = paparId;

            CurrentPaper = new PaperContext(paparId);
            await CurrentPaper.Initialize(this);

            if (WorkFlowPluginFunction != null)
            {
                IocResolver.Release(WorkFlowPluginFunction);
            }
            if (WorkFlowNodePluginFunction != null)
            {
                IocResolver.Release(WorkFlowNodePluginFunction);
            }

            WorkFlowPluginFunction = _workFlowPluginManager.GetWorkFlowDiyFunction(CurrentPaper.WorkFlow, IocResolver).Object;

            WorkFlowNodePluginFunction = _workFlowPluginManager.GetWorkFlowNodeDiyFunction(CurrentPaper.CurrentNode, IocResolver).Object;

            _traces = null;
            //需重新读取的数据
            _logData = null;
            _nextNodeListCache = null;

            ClearRecordsCache();
        }


        #region 稿件信息查询

        public long UserId => AbpSession.GetUserId();

        /// <summary>
        /// 获取意见记录(只读，不要修改list里的任何model)
        /// </summary>
        public async Task<List<WorkFlowProcessDto>> GetAllProcessDataAsync()
        {
            if (_processData == null || _processData.Count == 0)
            {
                var temp = await GetAllProcessDataWithArchiveAsync();
                _processData = temp.Where(c => c.State != ActionState.Archive).ToList();
            }
            return _processData;
        }

        //用于做数据恢复
        public async Task<List<WorkFlowProcessDto>> GetAllProcessDataWithArchiveAsync()
        {
            if (_processDataWithArchive == null || _processDataWithArchive.Count == 0)
            {
                _processDataWithArchive = await WorkFlowProcessStore.GetAllProcessDataWithArchiveAsync(this.PaperId);
            }
            return _processDataWithArchive;
        }

        public async Task<IList<WorkFlowLogDto>> GetLogDataAsync()
        {
            if (_logData == null)
            {
                _logData = await WokFlowLogStore.GetLogDataAsync(this.PaperId);
            }
            return _logData;
        }

        public async Task<IList<WorkFlowProcessDto>> GetRemarkDataAsync()
        {
            List<WorkFlowProcessDto> data = await GetAllProcessDataAsync();

            return data.Select(c => c.CloneANewOne()).ToList();
        }

        public void ClearRecordsCache()
        {
            _processDataWithArchive = null;
            _processData = null;
            _actionState = null;
            _currentProcessDataList = null;
            _currentProcessData = null;
            _workFlowRelationshipData = null;
            _workFlowRelationshipDataWithCanceled = null;
        }

        /// <summary>
        /// SetPaperIdAsync(Guid paparId)中setvalue
        /// </summary>
        public IWorkflowDefinition WorkFlow => CurrentPaper.WorkFlow;

        /// <summary>
        /// SetPaperIdAsync(Guid paparId)中setvalue
        /// </summary>
        public IWorkflowNodeDefinition CurrentNode => CurrentPaper.CurrentNode;

        public Guid WorkFlowId => WorkFlow.Definition.WorkFlowId;

        public Guid NodeId => CurrentNode.Definition.NodeId;

        public bool IsFirst => WorkFlow.FirstNode.Definition.NodeId == this.NodeId;

        public async Task<bool> IsLastAsync()
        {
            return !(await CanGoNextAsync());
        }

        public async Task<bool> CanGoNextAsync()
        {
            var nextList = await GetNextAsync();
            return nextList.Count > 0;
        }

        //弹窗选人的目的是为了确认两个参数，如果已经有了，还是要弹窗，但自动帮忙选上
        public async Task<IList<IWorkflowNodeDefinition>> GetNextAsync()
        {
            if (_nextNodeListCache != null)
            {
                return _nextNodeListCache.NextNodeList;
            }

            var nextIdList = this.CurrentNode.Definition.NextNodeList;
            if (!nextIdList.IsNullOrEmpty())
            {
                var list = WorkFlow.GetNodeList(nextIdList.ToList());
                list = await WorkFlowNodePluginFunction.CheckNextNodeListAsync(list, this);

                _nextNodeListCache = new NodeListCache { NextNodeList = list };
                return list;
            }

            _nextNodeListCache = new NodeListCache { NextNodeList = new List<IWorkflowNodeDefinition>() };
            return _nextNodeListCache.NextNodeList;
        }

        public async Task<WorkFlowProcessDto> GetCurrentProcessAsync()
        {
            if (_currentProcessData != null)
            {
                return _currentProcessData;
            }

            var list = await GetCurrentProcessListAsync();
            if (list != null && list.Count > 0)
            {
                if (list.Count == 1)
                {
                    _currentProcessData = list[0].CloneANewOne();
                }
                else
                {
                    //同时存在 传阅 与 办理 两种任务时，取后者
                    _currentProcessData = list.OrderByDescending(c => c.OperationType).ThenByDescending(c => c.Severity).FirstOrDefault().CloneANewOne();
                }
                return _currentProcessData;
            }

            return null;
        }

        private async Task<List<WorkFlowProcessDto>> GetCurrentProcessListAsync()
        {
            if (_currentProcessDataList != null)
            {
                return _currentProcessDataList;
            }

            var actionState = await CheckActionStateAsync(); //先修改状态
            if (actionState == ActionState.Todo)
            {
                var data = await GetAllProcessDataAsync();
                var list = new List<WorkFlowProcessDto>();
                foreach (var item in data)
                {
                    if (item.UserId == UserId && item.State == ActionState.Todo)
                    {
                        list.Add(item.CloneANewOne()); //传阅，办理等任务可能同时存在，即一个人有多项任务
                    }
                }
                _currentProcessDataList = list;
                return _currentProcessDataList;
            }
            return null;
        }


        public async Task<bool> IsBranchLineAsync()
        {
            var currentP = await GetCurrentProcessAsync();
            if (currentP != null)
            {
                return currentP.TrunkId != null;
            }
            return false;
        }

        /// <summary>
        /// 当前待办人在主线时 确定是否还有其他操作人员（判断是否可以提交下一步）
        /// </summary>
        public async Task<bool> IsMultiplePeopleAsync()
        {
            var currentP = await GetCurrentProcessAsync();
            if (currentP != null)
            {
                if (currentP.TrunkId == null)
                {
                    return await IsHasOtherOperatorAsync(currentP);
                }
            }

            return false;
        }

        public async Task<ActionState> CheckActionStateAsync()
        {
            if (_actionState == null)
            {
                _actionState = await GetActionState();
            }
            return _actionState.Value;
        }

        private async Task<ActionState> GetActionState()
        {
            bool related = false;
            bool toDo = false;
            var data = await GetAllProcessDataAsync();

            bool changed = false;

            foreach (var item in data)
            {
                if (item.UserId == UserId)
                {
                    related = true;
                    if (item.State == ActionState.Todo)
                    {
                        if (item.HasMarked == false)
                        {
                            changed = true;

                            //标记为已读
                            await WorkFlowProcessStore.SetHasMarkedAsync(item.Id);

                            await TryRemoveOtherOperatorIfNeedAsync(item);
                        }

                        var relationshipData = await GetWorkFlowRelationshipsAsync();
                        var list = relationshipData.Where(c => c.TaskId == item.Id && c.HasMarked == false).ToList();
                        if (list.Count > 0)
                        {
                            await WorkFlowProcessStore.SetRelationshipHasMarkedAsync(item.PaperId, item.Id);
                        }

                        toDo = true;
                    }
                }
            }

            if (changed)
            {
                ClearRecordsCache();
            }

            if (toDo)
            {
                return ActionState.Todo;
            }
            if (related)
            {
                //已办理或排队等待中
                return ActionState.Related;
            }
            return ActionState.None;
        }

        #endregion

        #region 转审，撤回等自定义操作（含静态构造函数）

        public async Task<List<WorkFlowActionDto>> GetActionListAsync()
        {
            return await _workFlowPluginManager.GetActionListAsync(this);
        }
        public async Task<StateWhenSubmit> CheckStateBeforeExecuteActionAsync(string actionName, object param)
        {
            using (var action = _workFlowPluginManager.GetAction(actionName, IocResolver))
            {
                return await action.Object.CheckStateBeforeActionAsync(this, param);
            }
        }
        public async Task ExecuteActionAsync(string actionName, object param)
        {
            using (var action = _workFlowPluginManager.GetAction(actionName, IocResolver))
            {
                await action.Object.OperateAsync(this, param);
            }

            await ResetRuntimeDataAsync();
        }

        public bool CanOperate(string actionName)
        {
            return this.CurrentNode.Definition.ActionList.Contains(actionName);
        }

        #endregion

        #region 流程流转

        #region 添加、删除日志记录

        /// <summary>
        /// 写入操作记录
        /// </summary>
        public async Task AddLogAsync(string message, long fromOperator, long? nextOperator, Guid? currentProcessId)
        {
            var userName = await UserAndUnitFinder.GetUserNameAsync(fromOperator);
            if (nextOperator == null)
            {
                await WokFlowLogStore.AddLogAsync(message, userName, "", PaperId, currentProcessId);
            }
            else
            {
                var nextUserName = await UserAndUnitFinder.GetUserNameAsync(nextOperator.Value);
                await WokFlowLogStore.AddLogAsync(message, userName, nextUserName, PaperId, currentProcessId);
            }
        }
        public async Task AddLogAsync(string message, string fromOperator, string nextOperator, Guid? currentProcessId)
        {
            await WokFlowLogStore.AddLogAsync(message, fromOperator, nextOperator, PaperId, currentProcessId);
        }

        #endregion


        /// <summary>
        /// 添加备注信息
        /// </summary>
        /// <param name="msg"></param>
        public async Task AddReplyAsync(string msg, string customData, bool hasRead)
        {
            var list = await GetCurrentProcessListAsync();
            if (list == null || list.Count == 0)
            {
                return;
            }

            if (list.Count == 1)
            {
                var defaultMsg = await WorkFlowNodePluginFunction.GetDefaultMsgAsync(this);
                await WorkFlowProcessStore.SaveReplyMsgAsync(list[0].Id, msg, customData, hasRead, defaultMsg == msg);
                return;
            }

            var current = await GetCurrentProcessAsync();

            // 领导可能同时存在待阅 和待审的任务，在办理的同时自动完成传阅
            foreach (var item in list)
            {
                if (item.OperationType == OperationType.PassRound)
                {
                    await WorkFlowProcessStore.SaveReplyMsgAsync(item.Id, "", null, hasRead, true);
                }
                else if (item.OperationType == OperationType.Processing && item.Id == current.Id)
                {
                    var defaultMsg = await WorkFlowNodePluginFunction.GetDefaultMsgAsync(this);
                    /*避免在不同分支存在多个待办任务的情况，不能自动完成分支的待办任务，否则可能稿件出错*/
                    await WorkFlowProcessStore.SaveReplyMsgAsync(item.Id, msg, customData, hasRead, defaultMsg == msg);
                }
            }
        }

        public async Task TryAddAdditionalMsg(string msg)
        {
            var current = await GetCurrentProcessAsync();
            await WorkFlowProcessStore.TryAddAdditionalMsg(msg, current);
        }

        public async Task<List<WorkFlowProcessMsgDto>> GetAllAdditionalMsg()
        {
            var list = await WorkFlowProcessStore.GetAllAdditionalMsgAsync(this.PaperId);
            var allData = await GetAllProcessDataAsync();
            return list.Where(c => allData.FirstOrDefault(d => d.Id == c.TaskId) != null).ToList();
        }

        #region 任务交接操作

        /// <inheritdoc/>
        public async Task HasSolved(
            string replyMsg, string defaultMsg, MoveMode moveMode, Action<WorkFlowProcessDto> action = null, bool force = false)
        {
            var list = await GetCurrentProcessListAsync();
            if (list == null || list.Count == 0)
            {
                return;
            }

            var current = await GetCurrentProcessAsync();
            var now = Clock.Now;

            if (list.Count == 1)
            {
                var item = list[0];
                if (string.IsNullOrEmpty(replyMsg))
                {
                    if (force)
                    {
                        item.Reply = replyMsg;
                        item.ReplyTime = now;
                    }
                    else if (item.Reply.IsNullOrEmpty() && item.OperationType == OperationType.Processing)
                    {
                        item.Reply = defaultMsg;
                        item.ReplyTime = now;
                        item.IsDefaultMsg = true;
                    }
                }
                else if (item.Reply != replyMsg)
                {
                    var defaultMsg2 = await WorkFlowNodePluginFunction.GetDefaultMsgAsync(this);
                    item.Reply = replyMsg;
                    item.ReplyTime = now;
                    item.IsDefaultMsg = defaultMsg2 == replyMsg;
                }

                item.FinishedTime = now;  //记录办理时间
                item.State = ActionState.Related;
                item.MovePattern = moveMode;
                item.HasRead = true;
                action?.Invoke(item);
                await WorkFlowProcessStore.UpdateAsync(item);

                return;
            }

            //同时结束 办理和传阅任务
            foreach (var item in list)
            {
                if (item.OperationType == OperationType.PassRound)
                {
                    item.FinishedTime = now;  //记录办理时间
                    item.State = ActionState.Related;
                    item.MovePattern = MoveMode.Leaf;
                    item.HasRead = true;
                    item.FinishedByTheWay = current.Id; //用于撤回时查找
                    action?.Invoke(item);
                    await WorkFlowProcessStore.UpdateAsync(item);
                }
                else if (item.OperationType == OperationType.Processing && item.Id == current.Id)
                {
                    if (string.IsNullOrEmpty(replyMsg))
                    {
                        if (force)
                        {
                            item.Reply = replyMsg;
                            item.ReplyTime = now;
                        }
                        else if (item.Reply.IsNullOrEmpty())
                        {
                            item.Reply = defaultMsg;
                            item.ReplyTime = now;
                            item.IsDefaultMsg = true;
                        }
                    }
                    else if (item.Reply != replyMsg)
                    {
                        var defaultMsg2 = await WorkFlowNodePluginFunction.GetDefaultMsgAsync(this);
                        item.Reply = replyMsg;
                        item.ReplyTime = now;
                        item.IsDefaultMsg = defaultMsg2 == replyMsg;
                    }

                    item.FinishedTime = now;  //记录办理时间
                    item.State = ActionState.Related;
                    item.MovePattern = moveMode;
                    item.HasRead = true;
                    action?.Invoke(item);
                    await WorkFlowProcessStore.UpdateAsync(item);
                }
            }
        }


        public async Task<bool> IsHasOtherOperatorAsync(WorkFlowProcessDto current)
        {
            var data = await GetAllOtherOperatorAsync(current);
            int count = data.Count;
            foreach (var item in data)
            {
                if (item.OperationType == OperationType.PassRound && item.EndNodeId != null && item.EndNodeId != this.NodeId)
                {
                    //传阅任务可以设置延后完成（EndNodeId设置的值必需是后续的必经步骤，否则稿件办结时会遗留未完成任务，也许会影响某些功能）
                    count--;
                }
            }
            return count > 0;
        }

        internal async Task<List<WorkFlowProcessDto>> GetAllOtherOperatorAsync(WorkFlowProcessDto current)
        {
            var result = new List<WorkFlowProcessDto>();
            if (current.TrunkId != null)
            {
                // 分支流程： 要查找 分支任务发起人 发起的所有分支（包括他们发起的下级分支）
                var records = await GetAllProcessDataAsync();
                //取Trunk的Code
                string code = records.FirstOrDefault(c => c.Id == current.TrunkId).Code;

                foreach (var item in records)
                {
                    //支线如果是多人并行的话，其他线路上可能发起新的支线，要确保这些支线上都没有待办或排队的人员
                    if (item.StepCode == current.StepCode && item.TrunkId != null && item.Code.StartsWith(code)
                        && item.Code != code && item.Id != current.Id)   //传阅只以并行的方式添加在主线
                    {
                        if (item.State == ActionState.Todo || item.State == ActionState.Waiting)
                        {
                            result.Add(item);
                        }
                    }
                }
            }
            else
            {
                var records = await GetAllProcessDataAsync();

                foreach (var item in records)
                {
                    if (item.Id != current.Id
                        && (item.State == ActionState.Todo || item.State == ActionState.Waiting))
                    {
                        //自己的当前待办任务
                        //（这里的实现上是支持一个人存在多个待办任务的情况，主线的人员添加操作没有做限制，也就是可能某人在支线上有任务的时候，主线又被添加了任务） 
                        // 会和传阅任务会一起办结
                        if (item.UserId != current.UserId || item.OperationType != OperationType.PassRound)
                        {
                            result.Add(item);
                        }
                    }
                }
            }
            return result;
        }

        private async Task<bool> IsOtherOperatorHasMarkedAsync(WorkFlowProcessDto current)
        {
            return await WorkFlowProcessStore.IsHas(c => c.PaperId == current.PaperId
                && c.UserId != current.UserId && c.State == ActionState.Todo && c.HasMarked);
        }
        private async Task TryRemoveOtherOperatorIfNeedAsync(WorkFlowProcessDto current)
        {
            if (current.ActionScheme == ActionScheme.OneOfMany)
            {
                //第一个查看稿件的人，自动移除其他备选人员（其他人员还没有看稿件）

                Expression<Func<WorkFlowProcess, bool>> p;

                if (current.TrunkId != null)
                {
                    p = c => c.PaperId == current.PaperId && c.UserId != current.UserId && c.State == ActionState.Todo
                        && c.TrunkId == current.TrunkId && c.OperationType == OperationType.Processing && c.ActionScheme == ActionScheme.OneOfMany;
                }
                else
                {
                    p = c => c.PaperId == current.PaperId && c.UserId != current.UserId && c.State == ActionState.Todo
                        && c.OperationType == OperationType.Processing && c.ActionScheme == ActionScheme.OneOfMany;
                }

                await WorkFlowProcessStore.RemoveAsync(p);
            }
        }

        /// <inheritdoc/>
        public async Task HandOverToNextInOrderAsync(WorkFlowProcessDto current, string replyMsg, string nextOperator = null)
        {
            //自己办结：
            //查找匹配的waiting，改变状态
            //更新当前过程状态

            await HasSolved(replyMsg, WorkFlowProcess.DefaultReplyMsg, MoveMode.Leaf);

            if (current.OperationType == OperationType.Processing)
            {
                await AddLogAsync("办理完毕", current.UserName, nextOperator, current?.Id);
            }
            else
            {
                await AddLogAsync("传阅完毕", current.UserName, nextOperator, current?.Id);
            }


            var data = await GetNextLevelProcessInOrderAsync(current);
            if (data.Count == 0)
            {
                return;
            }

            var now = Clock.Now; //移交时间
            foreach (var next in data)
            {
                next.StartTime = now;
                next.State = ActionState.Todo;
                next.PreOperatorId = current?.Id;
                await WorkFlowProcessStore.UpdateAsync(next);
            }
        }

        private async Task<List<WorkFlowProcessDto>> GetNextLevelProcessInOrderAsync(WorkFlowProcessDto currentProcess)
        {
            var data = await GetAllProcessDataAsync();

            //找寻排队等待的下一个审核人
            List<WorkFlowProcessDto> clmodelList = new List<WorkFlowProcessDto>();
            foreach (var item in data)
            {
                if (item.StepCode == currentProcess.StepCode
                    && item.TrunkId == currentProcess.TrunkId
                    && item.State == ActionState.Waiting)
                {
                    if (CheckeWaitingState(item, data, currentProcess))
                    {
                        clmodelList.Add(item.CloneANewOne());
                    }
                }
            }
            return clmodelList;
        }

        private bool CheckeWaitingState(WorkFlowProcessDto item, List<WorkFlowProcessDto> allData, WorkFlowProcessDto currentProcess)
        {
            var list = item.WaitingList.GetArryFromStrBySplit<Guid>(WorkFlowConst.SplitChars);
            bool flag = true;
            foreach (var id in list)
            {
                var ob = allData.FirstOrDefault(c => c.Id == id);
                if (ob != null)
                {
                    if (ob.State != ActionState.Related && ob.Id != currentProcess.Id)
                    {
                        flag = false;
                    }
                }
            }

            return flag;
        }

        /// <summary>
        /// 移交下一人（支线回归主线）
        /// </summary>
        /// <param name="current">接手人的操作状态数据</param>
        /// <returns></returns>
        private async Task<WorkFlowProcessDto> HandOverToTrunkAsync(WorkFlowProcessDto current)
        {
            WorkFlowProcessDto next = null;
            var data = await GetAllProcessDataAsync();
            foreach (var item in data)
            {
                if (item.Id == current.TrunkId.Value)
                {
                    next = item.CloneANewOne();
                    break;
                }
            }

            AddNewTaskByAlterOldTask(next, current, current.StepCode);
            await WorkFlowProcessStore.InsertAsync(next);
            return next;
        }

        #region 新任务添加

        ///  <inheritdoc/>
        public void AddNewTaskByAlterOldTask(WorkFlowProcessDto oldData, WorkFlowProcessDto current, int stepCode)
        {
            var now = Clock.Now;
            oldData.StartTime = now; //移交时间
            oldData.CreationTime = now;    //可能用于排序
            oldData.State = ActionState.Todo;
            oldData.Reply = "";
            oldData.ReplyTime = null;
            oldData.FinishedTime = null;
            oldData.HasMarked = false;
            oldData.MarkedTime = null;
            oldData.LastModificationTime = now;
            oldData.PreStepId = current?.Id;
            oldData.PreOperatorId = current?.Id;
            oldData.WaitingList = null;
            oldData.StepCode = stepCode;
            oldData.Id = Guid.NewGuid();
            oldData.Parallel = false;
            oldData.WaitingList = null;
        }
        ///  <inheritdoc/>
        public void ChangeProcessDataToArchive(WorkFlowProcessDto current, WorkFlowProcessDto item)
        {
            item.State = ActionState.Archive;
            item.MovePattern = MoveMode.Leaf;
            item.HasRead = false;
            item.IsHiddenInTable = true;
            item.Reply = "已取消";
            item.IsDefaultMsg = true;
            item.FinishedByTheWay = current.Id; //用于撤回时查找
        }

        public async Task<List<long>> GetToDoUserListAsync()
        {
            var records = await GetAllProcessDataAsync();
            var otherTodoUser = records
                .Where(c => (c.State == ActionState.Todo || c.State == ActionState.Waiting) && c.OperationType == OperationType.Processing)
                .Select(c => c.UserId)
                .ToList();

            return otherTodoUser;
        }
        public async Task<List<long>> RemoveToDoStateUserBeforeAddTaskAsync(List<long> userList)
        {
            if (userList == null)
            {
                return null;
            }

            var todoUsers = await GetToDoUserListAsync();
            return userList.Distinct().Where(c => !todoUsers.Contains(c)).ToList();
        }

        /// <inheritdoc/>
        public async Task AddNewTaskInTrunkAsync(
            WorkFlowProcessDto current, List<long> userIds,
            List<long> turnRoundUserList, Guid nodeId, bool isNewStep, ActionScheme actionScheme, Guid? responsibilityId)
        {
            List<WfUserQueueItem> users, turnRoundUsers;
            UserIdTransToUserQueueItems(userIds, turnRoundUserList, responsibilityId, false, out users, out turnRoundUsers);

            await AddNewTaskAsync(current,
                users,
                turnRoundUsers,
                nodeId, isNewStep, false, actionScheme);
        }
        /// <inheritdoc/>
        public async Task AddNewTaskInBranchAsync(
            [NotNull] WorkFlowProcessDto current, [NotNull] List<long> userIds, ActionScheme actionScheme, Guid? responsibilityId)
        {
            List<WfUserQueueItem> users, turnRoundUsers;
            UserIdTransToUserQueueItems(userIds, null, responsibilityId, true, out users, out turnRoundUsers);

            await AddNewTaskAsync(current,
                users,
                turnRoundUsers,
                current.NodeId, false, true, actionScheme);
        }

        private static void UserIdTransToUserQueueItems(
            List<long> userIds, List<long> turnRoundUserList,
            Guid? responsibilityId, bool asNewBranch,
            out List<WfUserQueueItem> users, out List<WfUserQueueItem> turnRoundUsers)
        {
            if (userIds.IsNullOrEmpty())
            {
                users = new List<WfUserQueueItem>();
            }
            else
            {
                users = userIds
                    .Select(c => new WfUserQueueItem
                    {
                        UserId = c,
                        OperationType = OperationType.Processing,
                        ResponsibilityId = responsibilityId,
                        CanEditForm = !asNewBranch
                    })
                    .ToList();
            }

            if (turnRoundUserList == null)
            {
                turnRoundUsers = new List<WfUserQueueItem>();
            }
            else
            {
                turnRoundUsers = turnRoundUserList
                    .Select(c => new WfUserQueueItem
                    {
                        UserId = c,
                        OperationType = OperationType.PassRound,
                        CanEditForm = false
                    })
                    .ToList();
            }
        }


        public async Task AddNewTaskInTrunkAsync(
            WorkFlowProcessDto current,
            [NotNull] List<WfUserQueueItem> users,
            List<WfUserQueueItem> turnRoundUser,
            Guid nodeId,
            bool isNewStep,
            ActionScheme actionScheme)
        {
            await AddNewTaskAsync(current, users, turnRoundUser, nodeId, isNewStep, false, actionScheme);
        }

        private async Task AddNewTaskAsync(
            WorkFlowProcessDto current,
            [NotNull] List<WfUserQueueItem> users,
            List<WfUserQueueItem> turnRoundUser,
            Guid nodeId,
            bool isNewStep,
            bool asNewBranch,
            ActionScheme actionScheme)
        {
            string parentCode;
            int lastUnitCode;
            Guid? trunkId;

            int stepCode = 1; //拟稿：current==null
            if (isNewStep)
            {
                if (current != null)
                {
                    //支持跨步骤完成
                    var allData = await GetAllProcessDataAsync();
                    stepCode = allData.Select(c => c.StepCode).Max() + 1;
                }
            }
            else
            {
                stepCode = current.StepCode;
            }

            if (isNewStep)
            {
                trunkId = null;
                parentCode = null;
                lastUnitCode = 0;
            }
            else
            {
                if (asNewBranch)
                {
                    trunkId = current?.Id;
                    parentCode = current.Code;
                    lastUnitCode = 0;
                }
                else
                {
                    //增加平级人员
                    trunkId = current?.TrunkId;

                    var lastCode = await WorkFlowProcessStore.GetLastCodeAsync(this.PaperId, trunkId, stepCode);
                    //同级至少有current这条数据存在，所以lastCode不会为null
                    parentCode = CodeHelper.GetParentCode(lastCode);
                    lastUnitCode = Convert.ToInt32(CodeHelper.GetLastUnitCode(lastCode));
                }
            }


            Queue<List<WfUserQueueItem>> userQueue = new Queue<List<WfUserQueueItem>>();
            var list = new List<WfUserQueueItem>();

            //传阅
            if (turnRoundUser != null)
            {
                list.AddRange(turnRoundUser.DistinctBy(c => c.UserId));
            }

            if (actionScheme == ActionScheme.Parallel || actionScheme == ActionScheme.OneOfMany)
            {
                list.AddRange(users.DistinctBy(c => c.UserId));
                userQueue.Enqueue(list);
            }
            else
            {
                users = users.DistinctBy(c => c.UserId).ToList();
                if (actionScheme == ActionScheme.DescOrder)
                {
                    users.Reverse();
                }

                if (users.Count > 0)
                {
                    for (int i = 0; i < users.Count; i++)
                    {
                        var item = users[i];
                        if (i == 0)
                        {
                            list.Add(item);
                            userQueue.Enqueue(list);
                        }
                        else
                        {
                            userQueue.Enqueue(new List<WfUserQueueItem> { item });
                        }
                    }
                }
                else
                {
                    userQueue.Enqueue(list);
                }
            }

            await AddNewTaskAsync(current, userQueue, nodeId, parentCode, lastUnitCode, actionScheme, trunkId, stepCode);
        }

        /// <inheritdoc/>
        public async Task<List<WorkFlowProcessDto>> AddNewTaskAsync(WorkFlowProcessDto current, [NotNull] Queue<List<WfUserQueueItem>> userQueue, Guid nodeId,
            string parentCode, int lastUnitCode, ActionScheme actionScheme, Guid? trunkId, int stepCode)
        {
            var list = new List<WorkFlowProcessDto>();
            var idList = new List<string>();
            string idStr = null;

            var now = Clock.Now;

            while (userQueue.Count > 0)
            {
                var users = userQueue.Dequeue();
                if (!idList.IsNullOrEmpty())
                {
                    idStr = string.Join(WorkFlowConst.SplitChars, idList);
                    idList.Clear();
                }

                foreach (var user in users)
                {
                    lastUnitCode++;
                    var newItem = new WorkFlowProcessDto
                    {
                        Id = Guid.NewGuid(),
                        UserId = user.UserId,
                        StartTime = now,
                        CreationTime = now,
                        PaperId = PaperId,
                        NodeId = nodeId,
                        WorkFlowId = WorkFlowId,
                        TrunkId = trunkId,
                        ActionScheme = actionScheme,
                        PreStepId = current?.Id,
                        PreOperatorId = current?.Id,
                        StepCode = stepCode,
                        HasRead = true,
                        ResponsibilityId = user.ResponsibilityId,
                        OperationType = user.OperationType,
                        Signal = user.Signal,
                        Signal2 = user.Signal2,
                        EndNodeId = user.TurnRoundUserEndNode,
                        Parallel = user.Parallel,
                        Severity = user.Severity,
                        CanEditForm = user.CanEditForm
                    };

                    newItem.Code = CodeHelper.AppendCode(parentCode, CodeHelper.CreateCode(lastUnitCode));

                    list.Add(newItem);
                    idList.Add(newItem.Id.ToString());

                    if (idStr.IsNullOrEmpty())
                    {
                        newItem.State = ActionState.Todo;
                    }
                    else
                    {
                        newItem.State = ActionState.Waiting;
                        newItem.WaitingList = idStr;
                    }

                    var userInfo = await UserAndUnitFinder.GetUserInfoAsync(newItem.UserId);
                    if (userInfo != null)
                    {
                        newItem.UserName = userInfo.UserName;
                        newItem.UserInfoDtoJson = userInfo.ToJsonString();
                    }
                }

            }

            foreach (var item in list)
            {
                await WorkFlowProcessStore.InsertAsync(item);
            }

            return list;
        }

        #endregion

        #endregion

        #region 下一步

        /// <summary>
        /// 下一步操作（主线流程前往下一步）
        /// </summary>
        /// <param name="nodeId"></param>
        /// <param name="userids_next">支线时无需传入</param>
        /// <param name="actionScheme_next">支线时无需传入</param>
        public async Task GoNextAsync(Guid nodeId, List<long> userids_next, List<long> turnRoundUserList, ActionScheme actionScheme_next, string replyMsg)
        {
            var paperState = this.CurrentPaper.PaperState;
            var actionState = await this.CheckActionStateAsync();
            if (paperState == PaperState.Draft || (paperState == PaperState.Running && actionState == ActionState.Todo))
            {
                var current = await GetCurrentProcessAsync();
                if (current.TrunkId == null)
                {
                    await WorkFlowNodePluginFunction.BeforeSendToNextNodeAsync(this, nodeId, userids_next, actionScheme_next, replyMsg);

                    var result = await WorkFlowNodePluginFunction.DiyGoNextAsync(this, nodeId, userids_next, turnRoundUserList, actionScheme_next, replyMsg);
                    if (!result)
                    {
                        bool isHasOtherOperator = await IsHasOtherOperatorAsync(current);
                        if (isHasOtherOperator)
                        {
                            await HandOverToNextInOrderAsync(current, replyMsg);
                        }
                        else
                        {
                            //自己办结
                            //移交下一步
                            await GoNext(current, userids_next, turnRoundUserList, nodeId, actionScheme_next, replyMsg);
                        }
                    }

                    await WorkFlowNodePluginFunction.AfterSendToNextNodeAsync(this);
                }
            }
        }

        /// <summary>
        /// 下一步操作（支线流程前往下一步）
        /// </summary>
        /// <returns>true表示符合本方法的调用条件</returns>
        public async Task<bool> GoNextAsync(string replyMsg)
        {
            var paperState = this.CurrentPaper.PaperState;
            var actionState = await this.CheckActionStateAsync();
            if (paperState == PaperState.Draft || (paperState == PaperState.Running && actionState == ActionState.Todo))
            {
                var current = await GetCurrentProcessAsync();
                if (current.TrunkId != null)
                {
                    bool isHasOtherOperator = await IsHasOtherOperatorAsync(current);
                    if (isHasOtherOperator)
                    {
                        await HandOverToNextInOrderAsync(current, replyMsg);
                    }
                    else
                    {
                        //自己办结
                        //送回主线
                        await BackToTrunk(current, replyMsg);
                    }

                    return true;
                }
            }

            return false;
        }


        /// <summary>
        /// 主线流程移交下一步
        /// </summary>
        /// <param name="current"></param>
        /// <param name="userids_next"></param>
        /// <param name="nodeId"></param>
        /// <param name="actionScheme_next"></param>
        public async Task GoNext(
            WorkFlowProcessDto current,
            List<long> userids_next,
            List<long> turnRoundUserList,
            Guid nodeId,
            ActionScheme actionScheme_next,
            string replyMsg,
            Action<WorkFlowProcessDto> action = null)
        {
            List<WfUserQueueItem> users, turnRoundUsers;
            UserIdTransToUserQueueItems(userids_next, turnRoundUserList, null, false, out users, out turnRoundUsers);

            await GoNext(current, users, turnRoundUsers, nodeId, actionScheme_next, replyMsg, action);
        }

        public async Task GoNext(
            WorkFlowProcessDto current, List<WfUserQueueItem> users_next, List<WfUserQueueItem> turnRoundUserList, Guid nodeId,
            ActionScheme actionScheme_next, string replyMsg,
            Action<WorkFlowProcessDto> action = null)
        {
            if (nodeId == Guid.Empty || (users_next.IsNullOrEmpty() && turnRoundUserList.IsNullOrEmpty()))
            {
                throw new UserFriendlyException("请选择人员及步骤");
            }
            if (users_next.IsNullOrEmpty())
            {
                users_next = new List<WfUserQueueItem>();
            }
            if (turnRoundUserList.IsNullOrEmpty())
            {
                turnRoundUserList = new List<WfUserQueueItem>();
            }

            if (users_next.Count + turnRoundUserList.Count == 1)
            {
                actionScheme_next = ActionScheme.Single;
            }
            //信息稿件的gcid
            CurrentPaper.Paper.ChangeNode(nodeId);
            CurrentPaper.Paper.ChangePaperState(PaperState.Running);

            //更新当前过程状态
            await HasSolved(replyMsg, WorkFlowProcess.DefaultReplyMsg, MoveMode.GoNext, action);
            //写入新任务
            await AddNewTaskAsync(current, users_next, turnRoundUserList, nodeId, true, false, actionScheme_next);

            var scheme = $"({EnumHelper.GetEnumDescription(actionScheme_next)})";

            var fromName = await UserAndUnitFinder.GetUserNameAsync(UserId);
            var nextNames = await UserAndUnitFinder.GetUserNameListAsync(users_next.Select(c => c.UserId).Distinct().ToList());
            string nextNameStr;
            if (turnRoundUserList.Count > 0)
            {
                var turnRoundUserName = await UserAndUnitFinder.GetUserNameListAsync(turnRoundUserList.Select(c => c.UserId).Distinct().ToList());
                nextNameStr = $"传阅：{turnRoundUserName.JoinAsString("、")}";
                if (nextNames.Count > 0)
                {
                    nextNameStr = $"传阅：{turnRoundUserName.JoinAsString("、")}；办理：{nextNames.JoinAsString("、")}";
                }
                else
                {
                    nextNameStr = $"传阅：{turnRoundUserName.JoinAsString("、")}";
                }
            }
            else
            {
                nextNameStr = nextNames.JoinAsString("、");
            }

            //写入记录
            await AddLogAsync("送" + this.WorkFlow.FindNode(nodeId).Definition.Name + scheme, fromName, nextNameStr, current?.Id);
        }

        /// <summary>
        /// 结束支线流程返回上一级流程
        /// </summary>
        /// <param name="current"></param>
        private async Task BackToTrunk(WorkFlowProcessDto current, string replyMsg)
        {
            //更新当前过程状态
            await HasSolved(replyMsg, WorkFlowProcess.DefaultReplyMsg, MoveMode.BackToTrunk);

            var next = await HandOverToTrunkAsync(current);

            //写入记录
            await AddLogAsync("送回" + CurrentNode.Definition.Name, UserId, next.UserId, current?.Id);
        }
        #endregion

        #region 退回

        public async Task<bool> CanGoback()
        {
            var paperState = this.CurrentPaper.PaperState;
            var isBranchLine = await IsBranchLineAsync();
            var actionState = await CheckActionStateAsync();
            if (paperState == PaperState.Running && actionState == ActionState.Todo && !isBranchLine)
            {
                Guid[] backList = this.CurrentNode.Definition.BackNodeList;
                if (!backList.IsNullOrEmpty())
                {
                    //获取已走过的轨迹
                    await GetTraces();

                    var hasNode = backList.Any(c => _traces.Contains(c));

                    if (hasNode)
                    {
                        //定制是否可以退回
                        return await WorkFlowNodePluginFunction.CanReturnAsync(this);
                    }
                }
            }
            return false;
        }

        public async Task<IList<IWorkflowNodeDefinition>> GetPreAsync()
        {
            var canGoback = await CanGoback();
            if (canGoback)
            {
                Guid[] backList = this.CurrentNode.Definition.BackNodeList;

                var list = backList.Where(c => _traces.Contains(c)).ToList();

                if (!list.IsNullOrEmpty())
                {
                    return WorkFlow.GetNodeList(list);
                }
            }
            return new List<IWorkflowNodeDefinition>();
        }

        /// <summary>
        /// 回退（必须在主线）如果是多人并行，当其他待办人员已查看了稿件后则不能退回，会抛出异常
        /// </summary>
        /// <param name="auditing"></param>
        /// <param name="gcid"></param>
        public async Task GoBackAsync(Guid nodeId, string replyMsg)
        {
            var paperState = this.CurrentPaper.PaperState;
            var actionState = await CheckActionStateAsync();
            if (paperState == PaperState.Running && actionState == ActionState.Todo)
            {
                var current = await GetCurrentProcessAsync();
                //确定在主线程
                if (current.TrunkId == null)
                {
                    var result = await WorkFlowNodePluginFunction.DiyReturnMethodAsync(this, current, nodeId, replyMsg);
                    if (!result)
                    {
                        var next = await GetBackProcessData(nodeId);

                        //确定要退回的那个流程存在
                        if (next != null)
                        {
                            var isOtherOperatorHasMarked = await IsOtherOperatorHasMarkedAsync(current);
                            if (isOtherOperatorHasMarked)
                            {
                                throw new UserFriendlyException("其他待办人员已查看了稿件，不能退回了！");
                            }
                            else
                            {
                                await GoBack(current, next, nodeId, replyMsg);
                            }
                        }
                    }

                    await ResetRuntimeDataAsync();
                }
            }
        }


        private async Task GetTraces()
        {
            if (this._traces.IsNullOrEmpty())
            {
                var data = await GetAllProcessDataAsync();
                this._traces = data.Select(c => c.NodeId).ToList();
            }
        }

        private async Task<WorkFlowProcessDto> GetBackProcessData(Guid nodeId)
        {
            var data = await GetAllProcessDataAsync();
            WorkFlowProcessDto result = null;
            foreach (var item in data)
            {
                if (item.TrunkId == null
                    && item.State == ActionState.Related
                    && item.NodeId == nodeId
                    && item.OperationType == OperationType.Processing
                    && item.FinishedTime != null)
                {
                    if (result == null || result.FinishedTime < item.FinishedTime)
                    {
                        result = item;
                    }
                }
            }

            if (result == null)
            {
                return null;
            }
            return result.CloneANewOne();
        }

        private async Task GoBack(WorkFlowProcessDto current, WorkFlowProcessDto next, Guid nodeId, string replyMsg)
        {
            //后退时，暂停其他的待办或等待状态的任务（不删除是为了撤回时恢复）
            var data = await GetAllOtherOperatorAsync(current);
            foreach (var item in data)
            {
                ChangeProcessDataToArchive(current, item);
                await WorkFlowProcessStore.UpdateAsync(item);
            }

            //更新当前过程状态
            await HasSolved(replyMsg, WorkFlowProcess.DefaultReplyMsg, MoveMode.GoBack);
            //写入新任务
            AddNewTaskByAlterOldTask(next, current, current.StepCode + 1);
            await WorkFlowProcessStore.InsertAsync(next);
            //写入记录
            await AddLogAsync("退回" + this.WorkFlow.FindNode(nodeId).Definition.Name, UserId, next.UserId, current?.Id);

            //信息稿件的gcid
            CurrentPaper.Paper.ChangeNode(nodeId);
            await _unitOfWorkManager.Current.SaveChangesAsync();
        }

        #endregion

        #region 添加新稿件（主线流程的入口）

        /// <summary>
        /// 添加新稿件（主线流程的入口）
        /// </summary>
        /// <param name="newPaper">新建稿件(未持久化)</param>
        public async Task AddManuscriptAsync(IWorkflowDefinition workflow, string title)
        {
            var userList = workflow.FirstNode.Definition.UserIdList;
            if (!userList.IsNullOrEmpty() && !userList.Contains(UserId))
            {
                throw new UserFriendlyException($"没有流程{workflow.Definition.Name}的拟稿权限！");
            }

            var currentUserInfo = await UserAndUnitFinder.GetCurrentUserInfoAsync();

            var query = from q in WorkFlowPaperRepository.GetAll()
                        orderby q.SerialNumber descending
                        select q.SerialNumber;
            var m = query.FirstOrDefault();

            var newPaper = new WorkFlowPaper(title,
                workflow.Definition.WorkFlowId,
                workflow.FirstNode.Definition.NodeId,
                currentUserInfo.UserName,
                m + 1);

            var paper = await WorkFlowPaperRepository.InsertAsync(newPaper);
            paper.ChangeUnit(currentUserInfo.MainOrgnzation.Id, currentUserInfo.MainOrgnzation.Name);
            paper.ChangeRegistrationTime(null);
            await _unitOfWorkManager.Current.SaveChangesAsync();

            await this.Initialize(paper.Id);

            await AddNewTaskInTrunkAsync(null, new List<long> { UserId }, null, NodeId, true, ActionScheme.Single, null);
            //拟稿添加的日志关联的MT_LC_ZT表的ID为0，目的是为了实现一次操作对应一条日志
            await AddLogAsync("拟稿", UserId, null, null);

            await WorkFlowPluginFunction.AfterPaperCreatedAsync(this);

            await ResetRuntimeDataAsync();
        }
        #endregion

        #endregion

        #region 用户查找

        public async Task<GetUserSelectionDataOutput> GetUserListForActionAsync(Guid? nodeId, List<long> unitIdList, [NotNull] string actionName)
        {
            using (var action = _workFlowPluginManager.GetAction(actionName, IocResolver))
            {
                return await action.Object.GetUserListAsync(this, nodeId, unitIdList);
            }
        }

        public async Task<GetUserSelectionDataOutput> GetUserListAsync(Guid? nodeId, List<long> unitIdList, UserFilter userFilter, string signal = null)
        {
            UserInfoDto autherInfo = null;
            if (userFilter != null && CurrentPaper.Paper.CreatorUserId != null)
            {
                autherInfo = await UserAndUnitFinder.GetUserInfoAsync(CurrentPaper.Paper.CreatorUserId.Value);
            }

            //人员和部门过滤不允许调整，所以放在方法内， 爱他参数则视情况定制
            List<long> limitedUnitIdList;
            if (unitIdList != null)
            {
                limitedUnitIdList = WorkFlow.Definition.UnitIdList.Where(c => unitIdList.Contains(c)).ToList();
            }
            else
            {
                limitedUnitIdList = WorkFlow.Definition.UnitIdList.ToList();
            }

            var sponsoringUnitId = CurrentPaper.Paper.UnitId;

            GetUserListResult result;
            if (nodeId != null)
            {
                var node = this.WorkFlow.FindNode(nodeId.Value);

                result = await UserAndUnitFinder.GetUserListAsync(limitedUnitIdList, node.Definition.UserIdList.ToList(), userFilter, autherInfo, sponsoringUnitId);
                result.Result.ActionScheme = node.Definition.ActionScheme;

                await WorkFlowNodePluginFunction.FilterUserListAsync(result, this, signal);
            }
            else
            {
                result = await UserAndUnitFinder.GetUserListAsync(limitedUnitIdList, null, userFilter, autherInfo, sponsoringUnitId);
                result.Result.ActionScheme = ActionScheme.Order;
            }

            return result.Result;
        }

        public async Task<List<WorkFlowRelationshipDto>> GetWorkFlowRelationshipsAsync()
        {
            if (_workFlowRelationshipData == null)
            {
                var temp = await GetWorkFlowRelationshipsWithCanceledAsync();
                _workFlowRelationshipData = temp.Where(c => c.IsCanceled == false).ToList();
            }
            return _workFlowRelationshipData;
        }

        public async Task<List<WorkFlowRelationshipDto>> GetWorkFlowRelationshipsWithCanceledAsync()
        {
            if (_workFlowRelationshipDataWithCanceled == null)
            {
                _workFlowRelationshipDataWithCanceled = await WorkFlowProcessStore.GetWorkFlowRelationshipsWithCanceledAAsync(this.PaperId);
            }
            return _workFlowRelationshipDataWithCanceled;
        }

        public async Task<ToDoUser> GetAllOtherToDoUserIdAsync(Func<WorkFlowProcessDto, bool> exclude)
        {
            var list = await WorkFlowProcessStore.GetAllOtherOperatorAsync(this.PaperId, this.UserId);
            var data = (await GetAllProcessDataAsync()).Select(c => c as IResponsibilityLink).ToList();
            var result = new ToDoUser { ToDoUserId = new List<long>(), ToReadUserId = new List<long>() };

            var workFlowRelationships = await GetWorkFlowRelationshipsAsync();

            foreach (var dto in list)
            {
                if (!exclude(dto))
                {
                    if (dto.OperationType == OperationType.Processing)
                    {
                        WorkFlowStaticFuncCollection.GetResponsibilityData(data, dto, result.ToDoUserId, workFlowRelationships);
                    }
                    else if (dto.OperationType == OperationType.PassRound)
                    {
                        result.ToReadUserId.Add(dto.UserId);
                    }
                }
            }
            result.ToDoUserId = result.ToDoUserId.Distinct().ToList();
            return result;
        }


        #endregion

        public void AdjustAprovealResultStatus()
        {
           
            //var entity = CurrentPaper.Paper;
            //var wfUniqueName = WorkFlow.Definition.CustomData?.UniqueName;
            //if (!DiyStaticFunction.IsApprovalFlow(wfUniqueName)) return;

            //ApprovalResult approvalResult = ApprovalResult.GongGongChi;
            //switch (CurrentNode.Definition.ShortName)
            //{
            //    case WorkFlowConst.CluesNodeConstant.ChuShen:
            //        approvalResult = ApprovalResult.ChuJiXs;
            //        break;
            //    case WorkFlowConst.CluesNodeConstant.FuShen:
            //        approvalResult = ApprovalResult.GaoJiXs;
            //        break;
            //    case WorkFlowConst.CluesNodeConstant.ZhongShen:
            //        approvalResult = ApprovalResult.ZhengShiSj;
            //        break;
            //}
            //entity.ChangeApprovalResult(approvalResult);
        }

        public async Task ResetRuntimeDataAsync()
        {
            await _unitOfWorkManager.Current.SaveChangesAsync();

            await ResetRuntimeDataAsync(this.PaperId);
        }
        private async Task ResetRuntimeDataAsync(Guid paperId)
        {
            var paper = await WorkFlowPaperRepository.FirstOrDefaultAsync(c => c.Id == paperId);

            if (paper == null || paper.PaperState == PaperState.Cancelled)
            {
                await WorkFlowPluginFunction.CleanRuntimeDataAsync(paperId, _workFlowRuntimeRepository);
            }

            var newAllData = await WorkFlowProcessStore.GetAllProcessDataAsync(paperId);
            await WorkFlowPluginFunction.ResetRuntimeDataAsync(paperId, _workFlowRuntimeRepository, newAllData);
        }

        private bool _isDisposed;

        public void Dispose()
        {
            LogHelper.Logger.Debug("WorkFlowManager Dispose");

            if (_isDisposed)
            {
                return;
            }

            _isDisposed = true;

            if (WorkFlowPluginFunction != null)
            {
                IocResolver.Release(WorkFlowPluginFunction);
            }
            if (WorkFlowNodePluginFunction != null)
            {
                IocResolver.Release(WorkFlowNodePluginFunction);
            }
        }
    }
}
